package cn.virens.common.easyexcel;

import cn.idev.excel.ExcelWriter;
import cn.idev.excel.write.metadata.WriteSheet;
import cn.virens.common.easyexcel.dict.ExcelDict;
import cn.virens.common.mybatis.entity.param.PageParam;
import cn.virens.common.mybatis.entity.result.PageResult;
import cn.virens.common.mybatis.entity.result.PageResultUtil;
import cn.virens.common.util.core.objcet.ObjectUtil;
import cn.virens.common.util.core.stream.StreamUtil;
import cn.virens.common.util.exception.APIException;
import org.dromara.hutool.core.text.split.SplitUtil;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ExcelExportExecutorMapBase<P extends PageParam> extends ExcelExportExecutorBase<P> {
    private final Map<String, ExcelDict> headerDict = new LinkedHashMap<>();
    private final Map<String, String> headerDefine = new LinkedHashMap<>();

    public ExcelExportExecutorMapBase(Integer pageSize, P pageParam) {
        super(pageSize, pageParam);
    }

    public ExcelExportExecutorMapBase(P pageParam) {
        super(pageParam);
    }

    @Override
    public void setProivde(Function<P, PageResult<?>> selectFun) throws APIException {
        super.setProivde(p -> PageResultUtil.format(selectFun.apply(p), result -> {
            return StreamUtil.parallelStream(result).map(rows -> {
                return headerDefine.keySet().stream().map(k -> {
                    return convert(getCellData(rows, k), k);
                }).toList();
            }).toList();
        }));
    }

    @Override
    public void exportSheet(ExcelWriter writer, WriteSheet sheet) throws IOException {
        sheet.setHead(getHeaderNameList());

        super.exportSheet(writer, sheet);
    }

    /**
     * 获取表头定义列表
     */
    protected List<List<String>> getHeaderNameList() throws APIException {
        return headerDefine.values().stream().map(headerName -> {
            return SplitUtil.split(headerName, ",");
        }).collect(Collectors.toList());
    }

    /**
     * 添加表头
     */
    public void addHeader(String key, String name, ExcelDict dict) {
        this.headerDefine.put(key, name);
        this.headerDict.put(key, dict);
    }

    /**
     * 添加表头
     */
    public void addHeader(String key, String name) {
        this.headerDefine.put(key, name);
    }

    /**
     * 获取单元格数据
     */
    protected Object getCellData(Object obj, String key) {
        if (obj instanceof Map<?, ?> map) {
            return map.get(key);
        }

        return ObjectUtil.get(obj, key);
    }

    /**
     * 获取单元格数据(并对有转换工具的列进行处理)
     */
    protected Object convert(Object obj, String key) {
        ExcelDict dict = headerDict.get(key);

        if (dict != null && obj != null) {
            obj = dict.toValue(obj);
            obj = dict.getKey(obj);
        }
        if (obj == null) {
            return "";
        }

        return obj;
    }

}
